import * as uuid from "uuid";
import Typings from "../../typings";

class MongooseController<T> {
  Model: T & Typings.Common.plainObj;

  constructor(Model: T & Typings.Common.plainObj) {
    this.Model = Model;
  }

  // 生成一个 uuid，CommonController 类的内部方法，实例化对象无法访问到该方法
  static GetUuid: () => string = () => uuid.v4();

  // 获取当前登录的用户id
  GetUserId: (req: Typings.Express.ConvertRequest) => string = (req) => {
    const { user } = <Typings.Express.ConvertRequest>req;
    return user?.id || "";
  };

  // 查询总数量
  Count: (query: Typings.Common.plainObj) => any = (query = {}) => {
    return this.Model.countDocuments(query);
  };

  // 查询
  Find: (query: Typings.Common.plainObj) => any = (query = {}) => {
    return this.Model.find(query);
  };

  // 保存
  SaveOne: (
    req: Typings.Express.Request,
    data: Typings.Common.plainObj
  ) => any = (req, data = {}) => {
    const id = MongooseController.GetUuid();
    const creatorId = this.GetUserId(req as Typings.Express.ConvertRequest);
    return new (this.Model as any)({
      ...data,
      id,
      createdTime: Date.now(),
      updatedTime: Date.now(),
      creatorId: creatorId || req.body?.creatorId,
    }).save();
  };

  // 单个更新
  UpdateOne: (
    query: Typings.Common.plainObj,
    updateContent: Typings.Common.plainObj
  ) => any = (query = {}, updateContent = {}) => {
    return this.Model.findOneAndUpdate(
      query,
      { ...updateContent, updatedTime: Date.now() },
      {
        new: true,
        runValidators: true /* 触发验证*/,
      }
    );
  };

  // 批量更新
  UpdateMany: (
    query: Typings.Common.plainObj,
    updateContent: Typings.Common.plainObj
  ) => any = (query = {}, updateContent = {}) => {
    return this.Model.updateMany(query, updateContent, {
      new: true,
      runValidators: true /* 触发验证*/,
    });
  };

  // 单个删除
  RemoveOne: (query: Typings.Common.plainObj) => any = (query = {}) => {
    return this.Model.findOneAndDelete(query);
  };

  // 批量删除
  DeleteMany: (query: Typings.Common.plainObj) => any = (query: {}) => {
    return this.Model.deleteMany(query);
  };
}

export default MongooseController;
